package com.xiaode.controller.admin.statistics;

import com.jfinal.kit.Kv;
import com.jfinal.kit.Prop;
import com.jfinal.kit.PropKit;
import com.jfinal.kit.Ret;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Record;
import com.jfinal.plugin.redis.Cache;
import com.jfinal.plugin.redis.Redis;
import com.xiaode.common.constant.Const;
import com.xiaode.common.model.Admin;
import com.xiaode.common.model.Example;
import com.xiaode.common.model.OrgClass;
import com.xiaode.common.model.Student;
import com.xiaode.plugin.influx.InfluxDbKit;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.*;
import java.util.stream.Collectors;

public class StatisticsService {

    /**
     * 积分排名
     *
     * @return
     */
    public Ret scoreSort() {
        Cache redis = Redis.use();
        //去除测试账号
        Prop use = PropKit.use("testAccount.properties");
        String studentAccount = use.get("studentAccount");
        List<String> strings = Arrays.asList(studentAccount.split(","));
        @SuppressWarnings("unchecked")
		Set<Integer> zrange = redis.zrevrange(Const.user.StudentScore, 0, 19 + strings.size());
        List<Student> students = new ArrayList<>(20 + strings.size());
        for (Integer integer : zrange) {
            Student student = redis.get(Const.user.Student + integer);
            students.add(student);
        }
        students = students.stream().filter(student -> !strings.contains(student.getAccountId().toString())).limit(20).collect(Collectors.toList());
        return Ret.ok("scoreSort", students);
    }

    /**
     * 榜样排名
     *
     * @return
     */
    public Ret exampleSort() {
        List<Record> records = Db.find("SELECT name,COUNT(*) num FROM `example` WHERE isDele = 0 GROUP BY name ORDER BY num DESC LIMIT 10");
        for (Record record : records) {
            Example example = Example.dao.findFirst("SELECT pictureUrl,label FROM `example` WHERE name = ? AND isDele = 0", record.getStr("name"));
            record.put("url", example.get("pictureUrl"));
            record.put("label", example.get("label"));
        }
        return Ret.ok("exampleSort", records);
    }

    /**
     * 每月之星
     *
     * @return
     */
    public Ret monthStar(Admin admin, Date date, Integer gradeId) {
        if (gradeId == null) {
            return Ret.ok("monthStar", new ArrayList<Record>());
        }
        //查询每月之星
        LocalDateTime localDateTime = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
        int year = localDateTime.getYear();
        int monthValue = localDateTime.getMonthValue();
//        Kv kv = Kv.by("clasId", classNo).set("yearValue", year).set("monthValue", monthValue);
        List<Integer> classIdList = Db.query("SELECT id FROM org_class WHERE adminGradeId = ? AND state = 1", gradeId);
    	if(classIdList.size() <= 0) {
    		return Ret.ok("monthStar", new ArrayList<Record>());
        }
        Kv kv = Kv.by("yearValue", year).set("monthValue", monthValue).set("clasIds", classIdList);
        //查询新版的月度之星
        List<Record> list = Db.template("monthStar", kv).find();
        //去除0分
        list = list.stream().filter(record -> record.getInt("score") > 0).collect(Collectors.toList());
        return Ret.ok("monthStar", list);
    }


    /**
     * 登录情况分析
     *
     * @param gradeId 年级id
     * @return
     */
    public Ret loginSituationAnalysis(Integer gradeId) {
        if (gradeId == null) {
            return Ret.ok().set("sumNum", 0).set("loginNum", 0).set("everyClasLoginNum", new ArrayList<Record>());
        }
        List<Record> recordList = Db.find("SELECT oc.id FROM org_class oc INNER JOIN org_grade og ON oc.adminGradeId = og.id WHERE og.id = ?", gradeId);
        List<Integer> idList = recordList.stream().map(record -> record.getInt("id")).collect(Collectors.toList());
        //查询年级全部人数
        Kv kv = Kv.by("idList", idList);
        Record sumNum = Db.template("findNumByClasId", kv).findFirst();
        //查询某班登录人数
        List<Record> records = Db.template("findNumGroupByClasId", kv).find();
        return Ret.ok().set("sumNum", sumNum).set("everyClasLoginNum", records);
    }

    /**
     * 在线情况分析
     *
     * @return
     */
    public Ret stuOnlineAnalysis(Integer gradeId) throws Exception {
        if (gradeId == null) {
            return Ret.ok("weekMap", new HashMap<>()).set("lastWeekMap", new HashMap<>()).set("sumWeekMap", new HashMap<>()).set("sumLastWeekMap", new HashMap<>());
        }
        Kv kv = Kv.by("gradeId", gradeId);
        List<Student> students = Student.dao.template("findStudentUnderGradeNode", kv).find();
        int size = students.size();
        Set<String> hashSet = students.stream().map(student -> student.getId() + "").collect(Collectors.toSet());
        LocalDateTime now = LocalDateTime.now();
        //查询当前日期
        int dayOfWeek = now.getDayOfWeek().getValue();
        HashMap<Integer, Integer> hashMap = new HashMap<>();
        for (int i = 0; i < dayOfWeek + 7; i++) {
            LocalDateTime localDateTime = now.minusDays(i);
            LocalDateTime startDay = localDateTime
                    .withHour(0)
                    .withMinute(0)
                    .withSecond(0)
                    .withNano(0);
            LocalDateTime endDay = localDateTime
                    .withHour(23)
                    .withMinute(59)
                    .withSecond(59);
            //查询目标日期的在线时长
            Long start = startDay.toInstant(ZoneOffset.of("+8")).toEpochMilli() / 1000;
            Long end = endDay.toInstant(ZoneOffset.of("+8")).toEpochMilli() / 1000;
            ArrayList<Object> list = new ArrayList<>();
            int sum = 0;
            for (int a = 1; a <= 4; a++) {
                list.add(a);
                Map<String, Integer> slog = InfluxDbKit.statisticsAllUseModularTime("slog", start.toString(), end.toString(), list);
                Set<Map.Entry<String, Integer>> entries = slog.entrySet();
                //判断学生是否属于目标届别
                entries = entries.stream().filter(entry -> hashSet.contains(entry.getKey())).collect(Collectors.toSet());
                //遍历登录时间,并统计
                Iterator<Map.Entry<String, Integer>> iterator = entries.iterator();
                while (iterator.hasNext()) {
                    Map.Entry<String, Integer> next = iterator.next();
                    Integer value = next.getValue();
                    sum += value;
                }
            }
            //保存登录时间
            hashMap.put(dayOfWeek - i, sum);
        }
        //处理集合中的元素,分为两个周
        Set<Map.Entry<Integer, Integer>> entries = hashMap.entrySet();
        Iterator<Map.Entry<Integer, Integer>> iterator = entries.iterator();
        HashMap<Integer, Integer> lastWeekMap = new HashMap<>();
        HashMap<Integer, Integer> sumLastWeekMap = new HashMap<>();
        HashMap<Integer, Integer> weekMap = new HashMap<>();
        HashMap<Integer, Integer> sumWeekMap = new HashMap<>();
        while (iterator.hasNext()) {
            Map.Entry<Integer, Integer> next = iterator.next();
            if (next.getKey() < 1) {
                lastWeekMap.put(7 + next.getKey(), (int) Math.ceil(next.getValue().doubleValue() / size));
                sumLastWeekMap.put(7 + next.getKey(), next.getValue());
            } else {
                weekMap.put(next.getKey(), (int) Math.ceil(next.getValue().doubleValue() / size));
                sumWeekMap.put(next.getKey(), next.getValue());
            }
        }
        return Ret.ok("weekMap", weekMap).set("lastWeekMap", lastWeekMap).set("sumWeekMap", sumWeekMap).set("sumLastWeekMap", sumLastWeekMap);
    }


    public Ret teaOnlineAnalysis(Integer gradeId) throws Exception {
        if (gradeId == null) {
            HashMap<Object, Object> hashMap = new HashMap<>();
            return Ret.ok("weekMap", hashMap).set("lastWeekMap", hashMap).set("sumWeekMap", hashMap).set("sumLastWeekMap", hashMap);
        }
        List<Record> records = Db.find("SELECT oa.adminId FROM org_class oc INNER JOIN org_admin oa ON oc.id = oa.stratumId AND oa.stratum = 3 AND oc.adminGradeId = ?", gradeId);
        List<Integer> adminIdList = records.stream().map(record -> record.getInt("adminId")).collect(Collectors.toList());
        int size = adminIdList.size();
        HashSet<Integer> hashSet = new HashSet<>(adminIdList);
        LocalDateTime now = LocalDateTime.now();
        //查询当前日期
        int dayOfWeek = now.getDayOfWeek().getValue();
        HashMap<Integer, Integer> hashMap = new HashMap<>();
        for (int i = 0; i < dayOfWeek + 7; i++) {
            LocalDateTime localDateTime = now.minusDays(i);
            LocalDateTime startDay = localDateTime
                    .withHour(0)
                    .withMinute(0)
                    .withSecond(0)
                    .withNano(0);
            LocalDateTime endDay = localDateTime
                    .withHour(23)
                    .withMinute(59)
                    .withSecond(59);
            //查询目标日期的在线时长
            Long start = startDay.toInstant(ZoneOffset.of("+8")).toEpochMilli() / 1000;
            Long end = endDay.toInstant(ZoneOffset.of("+8")).toEpochMilli() / 1000;
            ArrayList<Object> list = new ArrayList<>();
            int sum = 0;
            for (int a = 1; a <= 4; a++) {
                list.add(a);
                Map<String, Integer> slog = InfluxDbKit.statisticsAllUseModularTime("alog", start.toString(), end.toString(), list);
                Set<Map.Entry<String, Integer>> entries = slog.entrySet();
                //判断学生是否属于目标届别
                entries = entries.stream().filter(entry -> hashSet.contains(Integer.parseInt(entry.getKey()))).collect(Collectors.toSet());
                //遍历登录时间,并统计
                Iterator<Map.Entry<String, Integer>> iterator = entries.iterator();
                while (iterator.hasNext()) {
                    Map.Entry<String, Integer> next = iterator.next();
                    Integer value = next.getValue();
                    sum += value;
                }
            }
            //保存登录时间
            hashMap.put(dayOfWeek - i, sum);
        }
        //处理集合中的元素,分为两个周
        Set<Map.Entry<Integer, Integer>> entries = hashMap.entrySet();
        Iterator<Map.Entry<Integer, Integer>> iterator = entries.iterator();
        HashMap<Integer, Integer> lastWeekMap = new HashMap<>();
        HashMap<Integer, Integer> sumLastWeekMap = new HashMap<>();
        HashMap<Integer, Integer> weekMap = new HashMap<>();
        HashMap<Integer, Integer> sumWeekMap = new HashMap<>();
        while (iterator.hasNext()) {
            Map.Entry<Integer, Integer> next = iterator.next();
            if (next.getKey() < 1) {
                lastWeekMap.put(7 + next.getKey(), (int) Math.ceil(next.getValue().doubleValue() / size));
                sumLastWeekMap.put(7 + next.getKey(), next.getValue());
            } else {
                weekMap.put(next.getKey(), (int) Math.ceil(next.getValue().doubleValue() / size));
                sumWeekMap.put(next.getKey(), next.getValue());
            }
        }
        return Ret.ok("weekMap", weekMap).set("lastWeekMap", lastWeekMap).set("sumWeekMap", sumWeekMap).set("sumLastWeekMap", sumLastWeekMap);
    }

    /**
     * 在线时间段分析
     *
     * @param gradeId
     * @return
     */
    public Ret onlineSegement(Integer gradeId) throws Exception {
        if (gradeId == null) {
            ArrayList<Integer> list = new ArrayList<>();
            return Ret.ok("teaList", list).set("stuList", list);
        }
        //查询该届别教师Id
        List<OrgClass> admins = OrgClass.dao.find("SELECT adminId FROM org_admin WHERE stratum = 2 AND stratumId = ?", gradeId);
        Set<Integer> hashSet = admins.stream().map(adminClass -> adminClass.getAdminGradeId()).collect(Collectors.toSet());
        //查询该届别学生id
        Kv kv = Kv.by("gradeId", gradeId);
        List<Student> studentList = Student.dao.template("findStuByGradeId", kv).find();
        Set<Integer> studentIdSet = studentList.stream().map(student -> student.getId()).collect(Collectors.toSet());
        LocalDateTime now = LocalDateTime.now();
        ArrayList<Integer> teaList = new ArrayList<>();
        ArrayList<Integer> stuList = new ArrayList<>();
        LocalDateTime localDateTime = now.minusDays(1);
        LocalDateTime startDay = localDateTime
                .withHour(0)
                .withMinute(0)
                .withSecond(0)
                .withNano(0);
        LocalDateTime endDay = localDateTime
                .withHour(2)
                .withMinute(0)
                .withSecond(0);
        for (int i = 0; i < 12; i++) {
            LocalDateTime start = startDay.plusHours(2 * i);
            LocalDateTime end = endDay.plusHours(2 * i);
            //查询目标日期的在线时长
            Long startTime = start.toInstant(ZoneOffset.of("+8")).toEpochMilli() / 1000;
            Long endTime = end.toInstant(ZoneOffset.of("+8")).toEpochMilli() / 1000;
            int[] useIds = InfluxDbKit.statisticsTimeUse("alog", startTime.toString(), endTime.toString());
            if (useIds != null) {
                Long useNum = Arrays.stream(useIds).filter(value -> hashSet.contains(value)).count();
                teaList.add(useNum.intValue());
            } else {
                teaList.add(0);
            }
            int[] userIds = InfluxDbKit.statisticsTimeUse("slog", startTime.toString(), endTime.toString());
            if (userIds != null) {
                Long stuUseNum = Arrays.stream(userIds).filter(value -> studentIdSet.contains(value)).count();
                stuList.add(stuUseNum.intValue());
            } else {
                stuList.add(0);
            }

        }

        return Ret.ok("teaList", teaList).set("stuList", stuList);
    }

    /**
     * 模块使用时长分析
     *
     * @param gradeId 年级
     * @return
     */
    public Ret moduleUseDuration(Integer gradeId) throws Exception {
        if (gradeId == null) {
            HashMap<String, Integer> hashMap = new HashMap<>();
            return Ret.ok("moduleUseDurationMap", hashMap).set("sumTime", hashMap);
        }
        //查询该届别学生id
        Kv kv = Kv.by("gradeId", gradeId);
        List<Student> students = Student.dao.template("findStuByGradeId", kv).find();
        Set<Integer> studentIdSet = students.stream().map(student -> student.getId()).collect(Collectors.toSet());
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime localDateTime = now.minusDays(7);
        Long end = now.toInstant(ZoneOffset.of("+8")).toEpochMilli() / 1000;
        Long start = localDateTime.toInstant(ZoneOffset.of("+8")).toEpochMilli() / 1000;
        HashMap<String, Integer> hashMap = new HashMap<>();
        HashMap<String, Integer> sumHashMap = new HashMap<>();

        for (int i = 1; i <= 5; i++) {
            List<Object> modList = new ArrayList<>();
            modList.add(i);
            Map<String, Integer> slog = InfluxDbKit.statisticsAllUseModularTime("slog", start.toString(), end.toString(), modList);
            Set<Map.Entry<String, Integer>> entries = slog.entrySet();
            //求得当前届别的使用时长
            Set<Map.Entry<String, Integer>> collect = entries.stream().filter(entry -> studentIdSet.contains(Integer.parseInt(entry.getKey()))).collect(Collectors.toSet());
            Iterator<Map.Entry<String, Integer>> iterator = collect.iterator();
            Double sum = 0d;
            while (iterator.hasNext()) {
                Map.Entry<String, Integer> next = iterator.next();
                sum += next.getValue();
            }
            sumHashMap.put(Const.modularType.hashMap.get(i), sum.intValue());
            hashMap.put(Const.modularType.hashMap.get(i), (int) (Math.ceil(sum / studentIdSet.size())));
        }
        return Ret.ok("moduleUseDurationMap", hashMap).set("sumTime", sumHashMap);
    }
}
